﻿using System;
using System.Xml;
using Storm.TextEditor.Editor.CodeCompletion;

namespace Moonlite.Services.CodeCompletion
{
    public static class JassNativeObjectsReader
    {
        private const string Path = "Moonlite.Services.CodeCompletion.Resources.Xml.JassNativeObjects.xml";

        public static CompletionDataCollection Types = new CompletionDataCollection();
        public static CompletionDataCollection Natives = new CompletionDataCollection();
        public static CompletionDataCollection BJs = new CompletionDataCollection();
        public static CompletionDataCollection NativeVariables = new CompletionDataCollection();
        public static CompletionDataCollection BJVariables = new CompletionDataCollection();
        public static CompletionDataCollection Read()
        {
            XmlDocument document = new XmlDocument();
            document.Load(typeof(JassNativeObjectsReader).Assembly.GetManifestResourceStream(Path));
            CompletionDataCollection data = new CompletionDataCollection();
            foreach (XmlNode node in document.ChildNodes)
            {
                if (node.Name.ToLower() == "jass")
                {
                    foreach (XmlNode childNode in node.ChildNodes)
                    {
                        int imageIndex = -1;
                        CompletionDataCollection collection = null;
                        switch (childNode.Name.ToLower())
                        {
                            case "bjs":
                                imageIndex = JassCompletionDataProvider.ImageIndexMethod;
                                collection = BJs;
                                break;
                            case "natives":
                                imageIndex = JassCompletionDataProvider.ImageIndexMethod;
                                collection = Natives;
                                break;
                            case "types":
                                imageIndex = JassCompletionDataProvider.ImageIndexStruct;
                                collection = Types;
                                break;
                            default:
                                break;
                        }

                        string description = "";
                        string keywords = childNode.InnerText;
                        Array.ForEach(keywords.Split(new string[] { Environment.NewLine }, StringSplitOptions.None), keyword =>
                        {
                            keyword = keyword.Trim();
                            if (keyword != "")
                            {
                                IJassObject jassObject;
                                string[] dataKeywords = keyword.Split(' ');
                                if (dataKeywords[0] == "var")
                                {
                                    jassObject = new JassObjectVariable();
                                    jassObject.ObjectType = childNode.Name.ToLower() == "bjs" ? JassObjectType.BJ :
                                        childNode.Name.ToLower() == "natives" ? JassObjectType.Native : JassObjectType.BJ;

                                    JassObjectVariable variable = jassObject as JassObjectVariable;
                                    variable.Name = dataKeywords[2] == "array" ? dataKeywords[3] : dataKeywords[2];
                                    variable.Value = dataKeywords[2] == "array" ? "" : dataKeywords.Length > 3 ? dataKeywords[4] : "";
                                    variable.Type = dataKeywords[1];
                                    imageIndex = JassCompletionDataProvider.ImageIndexVariable;
                                    description = String.Format("{0} {1}{2}", variable.Type, variable.Name,
                                        (variable.Value.Length > 0 ? " " + variable.Value : ""));

                                    keyword = variable.Name;
                                }
                                else if (dataKeywords[0] == "bj" || dataKeywords[0] == "native")
                                {
                                    jassObject = new JassObjectMethod();
                                    jassObject.ObjectType = childNode.Name.ToLower() == "bjs" ? JassObjectType.BJ :
                                        childNode.Name.ToLower() == "natives" ? JassObjectType.Native : JassObjectType.BJ;

                                    string[] methodKeywords = new string[3];
                                    methodKeywords[0] = dataKeywords[0];
                                    string secondEntry = "";
                                    int entryIndex = 0;
                                    Array.ForEach(dataKeywords, dataEntry =>
                                    {
                                        if (entryIndex >= 1 && entryIndex < dataKeywords.Length - 1)
                                        {
                                            secondEntry += String.Format("{0} ", dataEntry);
                                        }

                                        entryIndex++;
                                    });

                                    methodKeywords[1] = secondEntry;
                                    methodKeywords[2] = dataKeywords[dataKeywords.Length - 1];
                                    JassObjectMethod method = jassObject as JassObjectMethod;
                                    int paranthesisIndex = methodKeywords[1].IndexOf("(");
                                    int endParanthesisIndex = methodKeywords[1].IndexOf(")");
                                    if (paranthesisIndex > -1 && endParanthesisIndex > -1)
                                    {
                                        string fullArguments = methodKeywords[1].Substring(paranthesisIndex + 1, endParanthesisIndex - paranthesisIndex - 1);
                                        methodKeywords[1] = methodKeywords[1].Remove(paranthesisIndex);
                                        method.Name = methodKeywords[1];
                                        method.Arguments = fullArguments;
                                        method.Returns = methodKeywords[2];
                                    }
                                    else
                                    {
                                        throw new Exception("Malformed object data");
                                    }

                                    description = String.Format("{0}{1} takes {2} returns {3}", (method.ObjectType == JassObjectType.Native ?
                                        "native " : "function "), method.Name, method.Arguments, method.Returns);

                                    imageIndex = JassCompletionDataProvider.ImageIndexMethod;
                                    keyword = method.Name;
                                }

                                DefaultCompletionData keywordData = new DefaultCompletionData(imageIndex, keyword, description);
                                data.Add(keywordData);
                                collection.Add(keywordData);
                            }
                        });
                    }
                }
            }

            return data;
        }
    }
}